package com.whosly.strategy.spring;

import java.lang.annotation.Annotation;
import java.util.Map;
import java.util.Set;

import com.google.common.base.Preconditions;
import com.whosly.strategy.IStrategy;
import com.whosly.strategy.container.IStrategyContainer;
import com.whosly.strategy.container.StrategyContainerImpl;
import com.whosly.strategy.manager.ContainerFactoryHolder;
import com.whosly.strategy.manager.ContainerProxyManager;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.BeansException;
import org.springframework.beans.factory.BeanFactory;
import org.springframework.beans.factory.BeanFactoryAware;
import org.springframework.beans.factory.DisposableBean;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ApplicationObjectSupport;
import org.springframework.util.ClassUtils;

/**
 * 在配置文件中手动注入<br>
 * &lt;bean class="com.whosly.strategy.spring.ManageSpringBeans"
 * lazy-init="false" /&gt;
 *
 * @author 袁洋 2014年7月16日
 */
@Slf4j
public class ManageSpringBeans<C, S extends IStrategy<C>> extends ApplicationObjectSupport
        implements DisposableBean, BeanFactoryAware {

	private static ApplicationContext context;

	// private static final CountDownLatch latch = new CountDownLatch(1);
	//
	// // 定时任务执行器
	// private static final ScheduledExecutorService retryExecutor = Executors
	// .newScheduledThreadPool(1);
	//
	// private static ScheduledFuture<ApplicationContext> retryFuture;

	/**
	 * {@link ApplicationContext#getBean(Class)} 获取spring beans
	 *
	 * @param <T>
	 *            T
	 *
	 * @param requiredType
	 *            bean类型
	 * @return 对应的bean
	 *
	 */
	public static <T> T getBean(final Class<T> requiredType) {
		return getContext().getBean(requiredType);
	}

	/**
	 * {@link ApplicationContext#getBean(Class)} 获取spring beans
	 *
	 * @param <T>
	 *            T
	 *
	 * @param beanName
	 *            beanName
	 * @return 对应的bean
	 *
	 */
	public static <T> T getBean(final String beanName) {
		assertContextInjected();

		@SuppressWarnings("unchecked")
		final T bean = (T) getContext().getBean(beanName);
		return bean;
	}

	/**
	 * {@link ApplicationContext#getBean(Class)} 获取spring beans
	 *
	 * @param <T>
	 *            T
	 *
	 * @param requiredType
	 *            bean类型
	 * @return 对应的bean
	 *
	 */
	public static <T> Map<String, T> getBeans(final Class<T> requiredType) {
		return getContext().getBeansOfType(requiredType);
	}

	/**
	 * 从annotation提取bean清单
	 *
	 * @param annotationType
	 *            annotation类型
	 * @return 标注了该annotation的beans
	 */
	public static Map<String, Object> getBeansWithAnnotation(
			final Class<? extends Annotation> annotationType) {
		return getContext().getBeansWithAnnotation(annotationType);
	}

	public static ApplicationContext getContext() {
		// if (context == null) {
		// retryFuture = retryExecutor.schedule(
		// new Callable<ApplicationContext>() {
		// @Override
		// public ApplicationContext call() throws Exception {
		// try {
		// latch.await();
		// } catch (final InterruptedException e) {
		// e.printStackTrace();
		// }
		// return context;
		// }
		// }, 800, TimeUnit.MILLISECONDS);
		//
		// try {
		// final ApplicationContext c = retryFuture.get();
		// return c;
		// } catch (final InterruptedException e) {
		// e.printStackTrace();
		// } catch (final ExecutionException e) {
		// e.printStackTrace();
		// }
		// }

		if(context == null){
			//context = getApplicationContext();
		}
		return context;
	}

	// 判断application是否为空
	private static void assertContextInjected() {
		Preconditions.checkArgument(context != null,
				"application未注入 ，请在springContext.xml中注入SpringHolder!");
	}

	private static void clear() {
		context = null;
	}

	@Override
	public void destroy() throws Exception {
		ManageSpringBeans.clear();
	}

	@Override
	public void initApplicationContext(
			final ApplicationContext applicationContext) {
		super.initApplicationContext(applicationContext);

		if(context == null){
			ManageSpringBeans.context = applicationContext;
		}

		// 容器初始化
		Set<String> keys = ContainerProxyManager.<C, S>get().getKeys();
		for (String interfaceName : keys) {
			try {
				Class<?> clazz = ClassUtils.forName(interfaceName, getClass().getClassLoader());
				if(!getApplicationContext().containsBean(clazz.getSimpleName())){
						// 只有未被注册的，才被注册
						Class<IStrategyContainer<C, S>> strategyContainerInterface = (Class<IStrategyContainer<C, S>>) getBean(clazz.getSimpleName());

						IStrategyContainer strategyContainerProxy = new StrategyContainerImpl(strategyContainerInterface){
							//.
						};

						ContainerFactoryHolder.<C, S>get().registry(clazz.getSimpleName(), strategyContainerProxy, strategyContainerInterface);

				}else{
					// TODO
					Object obj = getBean(clazz.getSimpleName());
					IStrategyContainer strategyContainerProxy = (IStrategyContainer) obj;
					ContainerFactoryHolder.<C, S>get().registry(clazz.getSimpleName(), strategyContainerProxy, strategyContainerProxy.getClass());
				}

			} catch (Throwable ex) {
				ex.printStackTrace();
				// Class not regularly loadable - can't determine a match that way.
			}
		}
        ContainerProxyManager.get().clear();

		/* test打印注册信息 ContainerFactoryHolder  */
        Set<String> rows = ContainerFactoryHolder.get().getRows();
        log.info("ContainerFactoryHolder :" + rows);
	}

	@Override
	public void setBeanFactory(final BeanFactory beanFactory)
			throws BeansException {
		// .
	}

}
